﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NumberInterface
{
  public interface INumber : IComparable
  {
    #region Assignment
    INumber Assign(double op);
    INumber Assign(int op);
    INumber Assign(string op);
    INumber Assign(uint op);
    INumber Assign(INumber op);
    #endregion
    #region Comparison
    int Compare(INumber op);
    int Compare(double op);
    int Compare(int op);
    int Compare(uint op);
    bool IsInf();
    bool IsNan();
    bool IsNumber();
    bool IsZero();
    #endregion
    #region Basic
    string Data { get; set; }
    INumber Copy();
    INumber Swap(INumber op);
    double ToDouble();
    int ToInt();
    uint ToUint(bool roundUp = false);
    void FixPrecision();
    uint Precision { get; set; }
    #endregion
    #region Arit
    //Self Operanding
    INumber Add(INumber op);
    INumber Add(double op);
    INumber Add(int op);

    INumber Subtract(INumber op);
    INumber Subtract(double op);
    INumber Subtract(int op);

    INumber Multiply(INumber op);
    INumber Multiply(double op);
    INumber Multiply(int op);

    INumber Divide(INumber op);
    INumber Divide(double op);
    INumber Divide(int op);

    INumber MultiplyAdd(INumber mul, INumber add);
    INumber MultiplySubtract(INumber mul, INumber sub);

    INumber Negate();

    INumber Power(INumber op);
    INumber Power(double op);
    INumber Power(int op);

    INumber Sqrt();
    INumber Square();

    //Other Operanding
    INumber Add(INumber op1, INumber op2);
    INumber Add(INumber op1, double op2);
    INumber Add(INumber op1, int op2);

    INumber Subtract(INumber op1, INumber op2);
    INumber Subtract(INumber op1, double op2);
    INumber Subtract(INumber op1, int op2);
    INumber Subtract(double op1, INumber op2);
    INumber Subtract(int op1, INumber op2);

    INumber Multiply(INumber op1, INumber op2);
    INumber Multiply(INumber op1, double op2);
    INumber Multiply(INumber op1, int op2);

    INumber Divide(INumber op1, INumber op2);
    INumber Divide(INumber op1, double op2);
    INumber Divide(INumber op1, int op2);
    INumber Divide(double op1, INumber op2);
    INumber Divide(int op1, INumber op2);

    INumber MultiplyAdd(INumber mul1, INumber mul2, INumber add);
    INumber MultiplySubtract(INumber mul1, INumber mul2, INumber sub);

    INumber Negate(INumber op);

    INumber Power(INumber op1, INumber op2);
    INumber Power(INumber op1, double op2);
    INumber Power(INumber op1, int op2);

    INumber Sqrt(INumber op);
    INumber Square(INumber op);
    #endregion
    #region Trig
    //Self Operanding
    INumber Sin();
    INumber Cos();
    INumber Tan();

    INumber ASin();
    INumber ACos();
    INumber ATan();
    INumber ATan2(INumber y, INumber x);

    INumber Sinh();
    INumber Cosh();
    INumber Tanh();

    INumber Sec();
    INumber Csc();
    INumber Cot();

    INumber Sech();
    INumber Csch();
    INumber Coth();

    INumber ASinh();
    INumber ACosh();
    INumber ATanh();

    //Other Operanding
    INumber Sin(INumber op);
    INumber Cos(INumber op);
    INumber Tan(INumber op);

    INumber ASin(INumber op);
    INumber ACos(INumber op);
    INumber ATan(INumber op);

    INumber Sinh(INumber op);
    INumber Cosh(INumber op);
    INumber Tanh(INumber op);

    INumber Sec(INumber op);
    INumber Csc(INumber op);
    INumber Cot(INumber op);

    INumber Sech(INumber op);
    INumber Csch(INumber op);
    INumber Coth(INumber op);

    INumber ASinh(INumber op);
    INumber ACosh(INumber op);
    INumber ATanh(INumber op);

    /// <summary>
    /// Sets sop to the sine of this object and cop to the cosine of this object
    /// </summary>
    /// <param name="sop"></param>
    /// <param name="cop"></param>
    void SinCos(ref INumber sop, ref INumber cop);
    #endregion
    #region Special
    //Self Operanding
    INumber Abs();
    INumber Ln();
    INumber Ln1p();
    INumber Log10();
    INumber Log2();
    INumber SetE();
    INumber SetEPow(INumber pow);
    INumber SetPI();

    //Other Operanding
    INumber Abs(INumber op);
    INumber Hypot(INumber op1, INumber op2);
    INumber Ln(INumber op);
    INumber Ln1p(INumber op);
    INumber Log10(INumber op);
    INumber Log2(INumber op);
    #endregion
  }
}